﻿using Controllers;
using Dto;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using MyProject;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection.Metadata;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using Util;

namespace Controllers
{
    
    [Route("api/user/[action]")]
    [ApiController]
    public class UserLoginController : BaseController
    {
        public IFreeSql _fsql;
        public UserLoginController(IFreeSql fsql)
        {
            _fsql = fsql;
        }

        [HttpPost]
        [AllowAnonymous]
        public ApiModel Login2([FromBody] LoginDto p)
        {
            if (string.IsNullOrWhiteSpace(p.Phone) || string.IsNullOrWhiteSpace(p.Password))
            {
                return apiModel(Status.Error, "账号或密码错误！");
            }
            return apiModel(Status.Success, "", new { userinfo = p });
        }
        //用户登录获取Token
        [HttpPost]
        [AllowAnonymous]//这个是开放接口不用认证，因为用户第一次登录没有Token
        public ApiModel Login([FromBody] LoginDto userDto)
        {
            if (string.IsNullOrWhiteSpace(userDto.Password) || string.IsNullOrWhiteSpace(userDto.Phone))
            {
                return apiModel(Status.Error, "账号或密码错误！");
            }
            var userinfo = _fsql.Select<UserInfo>().Where(a => a.Phone == userDto.Phone && a.Password == userDto.Password).First();
            if (userinfo == null)
            {
                var rester = Register(userDto);
                if (rester!=null)
                {
                    //生成token
                    var token = CreatToken(JsonConvert.SerializeObject(userinfo), 7 * 24 * 60);
                    return apiModel(Status.Success, "", new { token = token, userinfo = rester });
                }
                else
                {
                    return apiModel(Status.Error, "注册失败！");
                }
            }
            else
            {
                if (userinfo.LoginCount == null)
                {
                    userinfo.LoginCount = 0;
                }
                userinfo.LoginCount++;
                _fsql.Update<UserInfo>().SetSourceIgnore(userinfo, col => col == null).Where(a => a.UserId == userinfo.UserId).ExecuteAffrows();
                //生成token
                var token = CreatToken(JsonConvert.SerializeObject(userinfo), 7 * 24 * 60);
                return apiModel(Status.Success, "", new { token = token ,userinfo = userinfo});
            }
        }

        private UserInfo Register(LoginDto data)
        {
            var newuser = new UserInfo()
            {
                LoginCount = 1, 
                CreateTime = DateTime.Now,
                Phone = data.Phone,
                Password = data.Password,
            };
            var repo = _fsql.GetRepository<UserInfo>();
            repo.Insert(newuser);

            return newuser;
        }



        #region 生成用户Token
        /// <summary>
        /// 生成token
        /// 前端传过来header里加入Authorization字段 ： Bearer 空格+token
        /// </summary>
        /// <param name="jsonStr">用户实体json</param>
        /// <param name="minutes">Token过期时间</param>
        /// <returns></returns>
        public string CreatToken(string jsonStr, int minutes)
        {
            var claim = new Claim[]
            {
                new Claim("user",jsonStr),//用户信息,可以选择部分用户信息存入，方便根据前端请求Token获取对应信息（json格式）
                new Claim(ClaimTypes.Role,"user")//角色
            };

            //密钥
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSettings.IssuerSigningKey));
            //证书签名
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            //生成token
            var token = new JwtSecurityToken(JwtSettings.ValidIssuer//发布者
                                             , JwtSettings.ValidAudience//接收者
                                             , claim //用户信息角色信息
                                             , DateTime.Now//当前创建时间
                                             , DateTime.Now.AddMinutes(minutes)//过期时间
                                             , creds//证书签名
                                             );
            string tokenStr = new JwtSecurityTokenHandler().WriteToken(token);//写入token

            return tokenStr;//返回
        }
        #endregion
    }


}
